﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Collections.Specialized;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;

namespace BTSZap
{
    internal class Arguments
    {
        private int _MaxArgumentNameLength = 1;
        private int _MaxTypeNameLength = 1;
        private StringDictionary GetArguments(string[] args)
        {
            
            StringDictionary arguments = new StringDictionary();
            if (args == null)
                return arguments;
            foreach (string arg in args)
            {
                string[] KeyValuePair = arg.Split(new char[]{':','='},2);
                if (KeyValuePair.Length != 2)
                {
                    Error = true;
                    ErrorReason = string.Format(Properties.Resources.errUnknownArg, arg);
                    break;
                }
                else
                {
                    if (KeyValuePair[0].ToUpper() == "LANGUAGE") SwitchToLanguage(KeyValuePair[1]);
                    arguments.Add(KeyValuePair[0].ToUpper(), KeyValuePair[1]);
                }
            }
            return arguments;
        }

        private void SwitchToLanguage(string p)
        {
            Properties.Resources.Culture = new CultureInfo(p.ToLower());
        }

        private void InitFromDictionnary(StringDictionary arguments)
        {
            PropertyInfo[] propsInfo = this.GetType().GetProperties();
            
            foreach (PropertyInfo propInfo in propsInfo)
            {
                BrowsableAttribute browsableAttr = PropertyInfoHelper.GetFirstAttribute<BrowsableAttribute>(propInfo);
                if ((browsableAttr != null) && (!browsableAttr.Browsable)) continue;
                DefaultValueAttribute defaultAttr = PropertyInfoHelper.GetFirstAttribute<DefaultValueAttribute>(propInfo);
                DescriptionAttribute descriptionAttr = PropertyInfoHelper.GetFirstAttribute<DescriptionAttribute>(propInfo);
                string textDescription = Properties.Resources.ResourceManager.GetString(propInfo.Name,Properties.Resources.Culture );
                if (textDescription == null) textDescription = descriptionAttr == null ? string.Empty : descriptionAttr.Description;
                _MaxArgumentNameLength = Math.Max(_MaxArgumentNameLength,propInfo.Name.Length);
                _MaxTypeNameLength = Math.Max(_MaxTypeNameLength,propInfo.PropertyType.Name.Length);
                string key = propInfo.Name.ToUpper();
                if (arguments.ContainsKey(key))
                {
                    try
                    {
                        propInfo.SetValue(this, Convert.ChangeType(arguments[key], propInfo.PropertyType), null);
                    }
                    catch
                    {
                        Error = true;
                        ErrorReason = string.Format(Properties.Resources.errParseType, key, propInfo.PropertyType.Name, arguments[key]);
                        continue;
                    }
                }
                else
                    if (defaultAttr != null)
                    {
                        propInfo.SetValue(this, defaultAttr.Value, null);
                    }
                    else
                    {
                        Error = true;
                        ErrorReason = string.Format(Properties.Resources.errRequiredParam,propInfo.Name,textDescription);
                        continue;
                    }
                    
            }
        }

        private Arguments(string[] args)
        {
            StringDictionary argumentDictionnary = GetArguments(args);            
            InitFromDictionnary(argumentDictionnary);               
        }
        private Arguments(StringDictionary arguments)
        {
            InitFromDictionnary(arguments);            
        }
        private static Arguments _arguments;

        public static void Init(string[] args)
        {
            _arguments = new Arguments(args);
        }

        public static void Init(StringDictionary arguments)
        {
            _arguments = new Arguments(arguments);
        }
        [Browsable(false)]
        public static Arguments Current { get { return _arguments; } }

        public static string GetArgumentsDescrition()
        {
            PropertyInfo[] propsInfo = typeof(Arguments).GetProperties();
            StringBuilder bld = new StringBuilder();
            bld.AppendLine(Properties.Resources.msgParamUsage);
            bld.AppendLine("------------------");
            bld.AppendLine();
            foreach(PropertyInfo propInfo in propsInfo)
            {
                BrowsableAttribute browsableAttr = PropertyInfoHelper.GetFirstAttribute<BrowsableAttribute>(propInfo);
                if ((browsableAttr != null) && (!browsableAttr.Browsable)) continue;
                DefaultValueAttribute defaultAttr = PropertyInfoHelper.GetFirstAttribute<DefaultValueAttribute>(propInfo);
                DescriptionAttribute descriptionAttr = PropertyInfoHelper.GetFirstAttribute<DescriptionAttribute>(propInfo);
                string textDescription = Properties.Resources.ResourceManager.GetString(propInfo.Name,Properties.Resources.Culture);
                if (textDescription == null) textDescription = descriptionAttr == null ? string.Empty : descriptionAttr.Description;
                if ((defaultAttr != null)&&(defaultAttr.Value != null))
                {
                    bld.AppendLine(string.Format(" [{0}:{1}] Default={2}",propInfo.Name,propInfo.PropertyType.Name,defaultAttr.Value));
                }
                else
                    bld.AppendLine(string.Format(" {0}:{1}",propInfo.Name,propInfo.PropertyType.Name));
                if (textDescription != string.Empty)
                {
                   bld.Append("   ");
                   bld.AppendLine(textDescription);
                }
                bld.AppendLine();
            }
            return bld.ToString();
        }

        public string GetConfigurationDescription()
        {
            PropertyInfo[] propsInfo = typeof(Arguments).GetProperties();
            StringBuilder bld = new StringBuilder();
            
            bld.AppendLine(Properties.Resources.msgParamRun);
            bld.AppendLine("-------------------");
            bld.AppendLine();
            foreach (PropertyInfo propInfo in propsInfo)
            {
                BrowsableAttribute browsableAttr = PropertyInfoHelper.GetFirstAttribute<BrowsableAttribute>(propInfo);
                if ((browsableAttr != null) && (!browsableAttr.Browsable)) continue;
                bld.AppendFormat("{0,-" + _MaxArgumentNameLength.ToString() + "} : {1}\n", propInfo.Name, propInfo.GetValue(this, null));
            }
            return bld.ToString();
        }

        #region Properties declarations
        [Browsable(false)]
        public bool Error { get; set; }
        [Browsable(false)]
        public string ErrorReason { get; set; }

        [Description("Language code : EN = english, FR= French,...")]
        [DefaultValue(null)]
        public string Language { get; set; }

        [Description("Name of the BizTalk application to UnInstall")]
        public string ApplicationName { get; set; }

        [Description("If enabled, try to auto detect SQL Server and Management Database")]
        [DefaultValue(true)]
        public bool AutoDetectConfig { get; set; }

        [Description("!Name the database server instance hosting BizTalk management Db")]
        [DefaultValue(".")]
        public string DatabaseServer { get; set; }

        [Description("Name of the management DB")]
        [DefaultValue("BiztalkMgmtDb")]
        public string ManagementDatabase { get; set; }

        [Description("Try to Un-GAC assemblies on all Biztalk Server")]
        [DefaultValue(false)]
        public bool UnGAC{ get; set; }

        [Description("Enable restarting host instances after removing application")]
        [DefaultValue(true)]
        public bool RestartHostInstances { get; set; }

        [Description("Do a full stop before removing. I.E. Kill running instances")]
        [DefaultValue(true)]
        public bool FullStop { get; set; }

        [Description("Disable confirmation")]
        [DefaultValue(false)]
        public bool NoConfirmation { get; set; }

        [Description("Information Level")]
        [DefaultValue(2)]
        public int InfoLevel { get; set; }

        [Description("Name of the MSI for backup")]
        [DefaultValue(null)]
        public string BackupMSIFile { get; set; }

        [Description("The MSI to desinstall")]
        [DefaultValue(null)]
        public string MSI { get; set; }

        [Description("if true, halt on critical errors. Otherwise try to continue")]
        [DefaultValue(true)]
        public bool HaltOnError { get; set; }

        
        #endregion
    }
}
